﻿#include <ranges>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <iterator>
#include <sstream>
#include <string>
#include <type_traits>
#include <map>

// 求素数
std::vector<int> prime_numbers;
bool is_prime(int x)
{
    if (prime_numbers.empty())
        prime_numbers.push_back(2);

    auto iter = prime_numbers.begin();

    while ((*iter) * (*iter) <= x)
    {
        if (x % (*iter) == 0)
            return false;
        ++iter;
    }

    return true;
}

// tagke 的用法
auto print = [](char x) { std::cout << x; };
int main()
{
    auto const ints = { 0,1,2,3,4,5 };
    auto even = [](int i) { return 0 == i % 2; };
    auto square = [](int i) { return i * i; };

    // 组合视图的“管道”语法：即将上一次的输出给下次的使用
    /*
    * 1. 循环每个数据，输出为一个int数据
    * 2. 对int数据进行filer
    * 3. 对符合条件的数据进行变换，即对偶数进行乘方
    */
    for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
        std::cout << i << ' ';
    }

    std::cout << '\n';

    // 传统的“函数式”组合语法：
    for (int i : std::views::transform(std::views::filter(ints, even), square)) {
        std::cout << i << ' ';
    }
    std::cout << "\n";

    {
        std::vector<int> a{ 1,2,3 };
        for (int i : (a | std::views::reverse)) {
            std::cout << i << "\n";
        }
        // ranges 是惰性求值的
        std::cout << "\n\n\n前100个素数:\n\n";
        for (int i : std::views::iota(2) | std::views::filter(is_prime) | std::views::take(100))
        {
            prime_numbers.push_back(i);
            std::cout << i << ' ';
        }
    }
    {
        // take的用法
        std::cout << "\n\n\ntake 的用法:\n\n";
        constexpr char pi[]{ '3', '.', '1', '4', '1', '5', '9', '2' };

        // for_each 的用法
        std::ranges::for_each(pi | std::ranges::views::take(6), print);
        std::cout << '\n';

        std::ranges::for_each(std::ranges::take_view{ pi, 42 }, print); // safely takes only 8 chars
        std::cout << '\n';
    }
    {
        // iota
        std::cout << "\n\n\niota 用法：\n\n";
        // 会打印出：1 2 3 4 5 6 7 8 9，没有10
        for (int i : std::views::iota(1, 10))
            std::cout << i << ' ';
        std::cout << '\n';

        for (int i : std::views::iota(1) | std::views::take(9))
            std::cout << i << ' ';
        std::cout << '\n';
    }
    {
        // isstream
        std::cout << "\n\n\n isstream用法:\n\n";
        auto words = std::istringstream{ "today is yesterday’s tomorrow" };
        for (const auto& s : std::ranges::istream_view<std::string>(words)) {
            // quoted用于给字符串添加符号
            std::cout << std::quoted(s, '/') << ' ';
        }
        std::cout << '\n';

        auto floats = std::istringstream{ "1.1  2.2\t3.3\v4.4\f55\n66\r7.7  8.8" };
        std::ranges::copy(
            std::ranges::istream_view<float>(floats),
            std::ostream_iterator<float>{std::cout, ", "});
        std::cout << '\n';
    }
    {
        // all的使用
        std::cout << "\n\n\n all的使用:\n\n";
        std::vector<int> v{ 0,1,2,3,4,5 };
        // 取v的所有值
        for (int n : std::views::all(v) | std::views::take(3)) {
            std::cout << n << ' ';
        }

        static_assert(std::is_same<
            decltype(std::views::single(42)),
            std::ranges::single_view<int>
        >{});

        static_assert(std::is_same<
            decltype(std::views::all(v)),
            std::ranges::ref_view<std::vector<int, std::allocator<int>>>
        >{});

        int a[]{ 1,2,3,4 };
        static_assert(std::is_same<
            decltype(std::views::all(a)),
            std::ranges::ref_view<int[4]>
        >{});

        static_assert(std::is_same<
            decltype(std::ranges::subrange{ std::begin(a) + 1, std::end(a) - 1 }),
            std::ranges::subrange<int*, int*, std::ranges::subrange_kind(1)>
        > {});
    }
    {
        // elements的用法
        // 选定元素的特定位置的值
        std::cout << "\n\n\nelements的用法:\n\n";
        const std::vector<std::tuple<int, char, std::string>> vt{
            {1, 'A', "α"},
            {2, 'B', "β"},
            {3, 'C', "γ"},
            {4, 'D', "δ"},
            {5, 'E', "ε"},
        };
        std::cout << "所有tuple的第一个元素:\n";
        for (int const e : std::views::elements<0>(vt)) { std::cout << e << ' '; }
        std::cout << '\n';
        std::cout << "所有tuple的第二个元素:\n";
        for (char const e : std::views::elements<1>(vt)) { std::cout << e << ' '; }
        std::cout << '\n';
        std::cout << "所有tuple的第三个元素:\n";
        for (std::string const& e : std::views::elements<2>(vt)) { std::cout << e << ' '; }
        std::cout << '\n';

        std::vector<std::pair<int, char>> vt1{
            {1, 'A'},
            {2, 'B'},
            {3, 'C'},
            {4, 'D'},
            {5, 'E'},
        };
        std::cout << "所有pair的第一个元素:\n";
        for (int const e : std::views::elements<0>(vt1)) { std::cout << e << ' '; }
        std::cout << '\n';
        std::cout << "所有pair的第二个元素:\n";
        for (char const e : std::views::elements<1>(vt1)) { std::cout << e << ' '; }
        std::cout << '\n';
    }
    {
        // take_while 就是满足条件的就take
        std::cout<<"\n\n\ntake_while 的用法:\n\n";
        for (int year : std::views::iota(2017)
            | std::views::take_while([](int y) { return y <= 2020; })) {
            std::cout << year << ' ';
        }
        std::cout << '\n';

        const char idea[]{ "Today is yesterday's tomorrow!.." };
        for (char x : std::ranges::take_while_view(idea, [](char c) { return c != '.'; })) {
            std::cout << x;
        }
        std::cout << '\n';
    }
    {
        // keys view 接受pair，tuple,map等的类型，并只需要它的key
        std::cout << "\n\n\keys的使用\n\n";
        const std::vector<std::pair<std::string, double>> quark_mass{ // MeV/c²
            {"up", 2.3},      {"down", 4.8},
            {"charm", 1275},  {"strange", 95},
            {"top", 173'210}, {"bottom", 4'180},
        };

        std::cout << "quark name:  │ ";
        for (std::string const& name : std::views::keys(quark_mass))
            std::cout << std::setw(9) << name << " │ ";

        std::cout << "\n" "mass MeV/c²: │ ";
        for (const double mass : std::views::values(quark_mass))
            std::cout << std::setw(9) << mass << " │ ";
        std::cout << '\n';
    }
    {
        // 同上面相反
        std::cout << "\n\n\nvalues的用法:\n\n";
        std::map<char, int> map{ {'A', 1}, {'B', 2}, {'C', 3}, {'D', 4}, {'E', 5} };

        auto odd = [](int x) { return 0 != (x & 1); };

        std::cout << "Odd values in the map: ";
        for (int value : map | std::views::values | std::views::filter(odd))
            std::cout << value << ' ';

    }
    {
        // reverse的用法
        std::cout << "\n\n\nreverse的用法:\n\n";
        static constexpr auto il = { 3, 1, 4, 1, 5, 9 };

        std::ranges::reverse_view rv{ il };
        for (int i : rv)
            std::cout << i << ' ';

        std::cout << '\n';

        for (int i : il | std::views::reverse)
            std::cout << i << ' ';
    }
    {
        // counted 的用法
        std::cout << "\n\n\n counted 的用法:\n\n";
        const int a[] = { 1, 2, 3, 4, 5, 6, 7 };
        for (int i : std::views::counted(a, 3))
            std::cout << i << ' ';
        std::cout << '\n';

        const auto il = { 1, 2, 3, 4, 5 };
        for (int i : std::views::counted(il.begin() + 1, 3))
            std::cout << i << ' ';
        std::cout << '\n';
    }
}